// `include "./datapath/im.v"
// `include "./datapath/pc.v"
// `include "./datapath/npc.v"
// `include "./datapath/reg.v"
// `include "./datapath/alu.v"
// `include "./control/alu_ctr.v"
// `include "./control/mux.v"
// `include "./datapath/dm.v"
// `include "./datapath/ext.v"
// `include "./datapath/pc_adder.v"
// `include "./datapath/reg_if_id.v"
// `include "./datapath/pc_ander.v"
// `include "./datapath/reg_id_ex.v"
`include "./mips/datapath/im.v"
`include "./mips/datapath/pc.v"
`include "./mips/datapath/alu.v" 
`include "./mips/control/alu_ctr.v"
`include "./mips/control/mux.v"
`include "./mips/datapath/dm.v"
`include "./mips/datapath/ext.v"
`include "./mips/datapath/reg.v"
`include "./mips/datapath/pc_adder.v"
`include "./mips/datapath/reg_if_id.v"
`include "./mips/datapath/pc_src_chooser.v"
`include "./mips/datapath/reg_id_ex.v"
`include "./mips/datapath/npc.v"
`include "./mips/datapath/reg_ex_mem.v"
`include "./mips/datapath/reg_mem_wb.v"
module Datapath(RegDes, Branch, MemtoReg, AluOp, MemWrite,AluSrc, RegWrite, Jump, Sign,DataType,DataSign,clk, rst, instr);

    input [1:0] RegDes;      
    input [1:0] Branch;      
    input [1:0] MemtoReg; 
    input AluSrc;      
    input[3:0] AluOp;  
    input MemWrite;    
    input RegWrite;    
    input [1:0]   Jump;        
    input Sign;
    input [1:0]   DataType;
    input         DataSign;
    input clk;        
    input rst;    
    output [31:0] instr;

    wire   [31:0]  im_instr_out;           
    wire   [31:0]  writedata;  
    wire   [31:0]  data_rs, data_rt;        
    wire   [31:0]  result;     
        
    wire [31:0] mux_pc_out;
    wire[31:0] pc_out;
    wire [31:0] pc_adder_out;

    MuxPc mux_pc(pc_src_chooser_pc_src_out,pc_adder_out,reg_ex_mem_next_pc_out,mux_pc_out);
    Pc pc(mux_pc_out, clk, rst, pc_out);
    PcAdder pc_adder(pc_out,pc_adder_out);
    
    

    im_4k im(pc_out[11:0],im_instr_out);

    wire [31:0] reg_if_id_pc_out;
    wire [31:0] reg_if_id_instr_out;
    RegIfId reg_if_id(pc_adder_out,im_instr_out,reg_if_id_pc_out,reg_if_id_instr_out,clk);
    assign instr = reg_if_id_instr_out;
    wire [31:0] reg_rs_out;
    wire [31:0] reg_rt_out;
    Reg regfile(reg_if_id_instr_out[25:21], reg_if_id_instr_out[20:16], reg_mem_wb_dm_des_reg_out, reg_mem_wb_RegWrite_out,mux_reg_data_write_data_out, clk,rst,reg_rs_out,reg_rt_out);

    wire   [1:0]    reg_id_ex_RegDst_out;      
    wire   [1:0]    reg_id_ex_Branch_out;      
    wire   [1:0]    reg_id_ex_MemtoReg_out;   
    wire            reg_id_ex_AluSrc_out;      
    wire   [3:0]    reg_id_ex_AluOp_out;  
    wire            reg_id_ex_MemWrite_out;    
    wire            reg_id_ex_RegWrite_out;    
    wire   [1:0]    reg_id_ex_Jump_out;        
    wire            reg_id_ex_Sign_out;
    wire   [31:0]   reg_id_ex_pc_out;
    wire   [31:0]   reg_id_ex_data_rs_out;
    wire   [31:0]   reg_id_ex_data_rt_out;
    wire   [15:0]   reg_id_ex_immediate_out;
    wire   [4:0]    reg_id_ex_instr1_out;
    wire   [4:0]    reg_id_ex_instr2_out;
    wire   [31:0]   reg_id_ex_instr_out;
    wire   [1:0]    reg_id_ex_DataType_out;
    wire            reg_id_ex_DataSign_out;
   RegIdEx reg_id_ex(RegDes,Branch,MemtoReg,AluOp,MemWrite,AluSrc,RegWrite,Jump,Sign,DataType,DataSign,reg_if_id_pc_out,
    reg_rs_out,reg_rt_out,reg_if_id_instr_out[15:0],reg_if_id_instr_out[20:16],reg_if_id_instr_out[15:11],reg_if_id_instr_out,clk,
    reg_id_ex_RegDst_out,     
    reg_id_ex_Branch_out,     
    reg_id_ex_MemtoReg_out,   
    reg_id_ex_AluOp_out, 
    reg_id_ex_MemWrite_out,  
    reg_id_ex_AluSrc_out,
    reg_id_ex_RegWrite_out,   
    reg_id_ex_Jump_out,       
    reg_id_ex_Sign_out,
    reg_id_ex_pc_out,
    reg_id_ex_data_rs_out,
    reg_id_ex_data_rt_out,
    reg_id_ex_immediate_out,
    reg_id_ex_instr1_out,
    reg_id_ex_instr2_out,
    reg_id_ex_instr_out,
    reg_id_ex_DataType_out,
    reg_id_ex_DataSign_out
    );

    wire [31:0] npc_next_pc_out;
    Npc npc(reg_id_ex_pc_out,extender_immediate_out,reg_id_ex_data_rs_out,reg_id_ex_Jump_out,reg_id_ex_Branch_out, reg_id_ex_instr_out,npc_next_pc_out);

    wire [31:0] extender_immediate_out;
    Extender extender(reg_id_ex_immediate_out,reg_id_ex_Sign_out,extender_immediate_out);

    wire [31:0] mux_alu_out;
    wire alu_ctrl_alu_src_a_out;
    MuxAlu mux_alu(reg_id_ex_data_rt_out, extender_immediate_out,reg_id_ex_AluSrc_out,mux_alu_out);

    wire   [ 3:0]  AluCtrl; 
    AluControl alu_ctr(reg_id_ex_AluOp_out,reg_id_ex_immediate_out[5:0],AluCtrl);

    wire alu_zero_out;
    wire [31:0] alu_result_out;
    Alu alu( AluCtrl,reg_id_ex_data_rs_out , mux_alu_out,reg_id_ex_immediate_out[10:6],alu_zero_out, alu_result_out);

    wire [4:0] mux_reg_des_reg;
    MuxReg mux_reg(reg_id_ex_instr1_out, reg_id_ex_instr2_out, reg_id_ex_RegDst_out, mux_reg_des_reg);

    wire [1:0]      reg_ex_mem_Branch_out;
    wire [1:0]      reg_ex_mem_MemtoReg_out;
    wire            reg_ex_mem_MemWrite_out;
    wire [1:0]      reg_ex_mem_Jump_out;
    wire            reg_ex_mem_RegWrite_out;
    wire [31:0]     reg_ex_mem_pc_out;
    wire [31:0]     reg_ex_mem_next_pc_out;
    wire            reg_ex_mem_zero_out;
    wire [31:0]     reg_ex_mem_result_out;
    wire [31:0]     reg_ex_mem_data_rt_out;
    wire [4:0]      reg_ex_mem_des_reg_out;
    wire [1:0]      reg_ex_mem_DataType_out;
    wire            reg_ex_mem_DataSign_out;
    RegExMem reg_ex_mem( reg_id_ex_Branch_out,reg_id_ex_MemtoReg_out, reg_id_ex_MemWrite_out,reg_id_ex_RegWrite_out,reg_id_ex_Jump_out,reg_id_ex_DataType_out,reg_id_ex_DataSign_out,reg_id_ex_pc_out,npc_next_pc_out,  alu_result_out, alu_zero_out,reg_id_ex_data_rt_out, mux_reg_des_reg,clk,reg_ex_mem_Branch_out,reg_ex_mem_MemtoReg_out,reg_ex_mem_MemWrite_out,reg_ex_mem_RegWrite_out,reg_ex_mem_Jump_out,reg_ex_mem_DataType_out,reg_ex_mem_DataSign_out,reg_ex_mem_pc_out,reg_ex_mem_next_pc_out,reg_ex_mem_zero_out,reg_ex_mem_result_out,reg_ex_mem_data_rt_out,reg_ex_mem_des_reg_out);

    wire pc_src_chooser_pc_src_out;
    PcSrcChooser pc_src_chooser(reg_ex_mem_Branch_out,reg_ex_mem_Jump_out,reg_ex_mem_zero_out,pc_src_chooser_pc_src_out);

    wire [31:0] dm_data_out;
    dm_4k dm(reg_ex_mem_result_out[11:0], reg_ex_mem_data_rt_out, reg_ex_mem_MemWrite_out,reg_ex_mem_DataType_out,reg_ex_mem_DataSign_out, clk, dm_data_out);

    wire [1:0]  reg_mem_wb_MemtoReg_out;
    wire        reg_mem_wb_RegWrite_out;
    wire [31:0] reg_mem_wb_dm_data_out;
    wire [31:0] reg_mem_wb_alu_result_out;
    wire [4:0]  reg_mem_wb_dm_des_reg_out;
    wire [31:0] reg_mem_wb_pc_out;
    RegMemWb reg_mem_wb(reg_ex_mem_MemtoReg_out,reg_ex_mem_RegWrite_out,dm_data_out,reg_ex_mem_result_out,reg_ex_mem_des_reg_out,reg_ex_mem_pc_out,clk,reg_mem_wb_MemtoReg_out,reg_mem_wb_RegWrite_out,reg_mem_wb_dm_data_out,reg_mem_wb_alu_result_out,reg_mem_wb_dm_des_reg_out,reg_mem_wb_pc_out);

    wire [31:0] mux_reg_data_write_data_out;
    MuxRegData mux_reg_data(reg_mem_wb_dm_data_out,reg_mem_wb_alu_result_out,reg_mem_wb_pc_out,reg_mem_wb_MemtoReg_out,mux_reg_data_write_data_out);
    
endmodule